package com.qfedu.user.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qfedu.common.core.entity.User;
import com.qfedu.common.core.enums.RedisKeyEnum;
import com.qfedu.common.core.enums.SmsEnum;
import com.qfedu.common.core.utils.JwtUtils;
import com.qfedu.common.core.utils.UserUtils;
import com.qfedu.common.minio.utils.MinioUtil;
import com.qfedu.common.neo4j.node.UserNode;
import com.qfedu.common.neo4j.utils.Neo4jUtils;
import com.qfedu.common.sms.utils.AliSmsUtils;
import com.qfedu.common.utils.RedisUtil;
import com.qfedu.user.mapper.UserMapper;
import com.qfedu.user.param.LoginParam;
import com.qfedu.user.param.RegisterParam;
import com.qfedu.user.service.UserService;
import com.qfedu.user.vo.MyVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 以梦为马，以汗为泉，不忘初心，不负韶华
 *
 * @author zqh
 * @version 1.0
 * @data 2025/6/2 17:48
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private Neo4jUtils neo4jUtils;
    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private MinioUtil minioUtil;

    /**
     * 写逻辑本质上就是操作数据，一定要明确有哪些数据
     * 需要什么数据，需要操作那些表，需要对这些表进行CRUD那种操作
     * @param registerParam
     */
    @Override
    public void register(RegisterParam registerParam) {

//        判空
        if (registerParam.getPhone() == null || registerParam.getPhone().equals("")) {
            throw new RuntimeException("必须设置手机号");
        }
        if (!StringUtils.hasLength(registerParam.getUsername())) {
            throw new RuntimeException("用户名不能为空");
        }
        if ( registerParam.getPassword() == null || registerParam.getPassword().equals("")){
            throw new RuntimeException("密码不能为空");
        }


//        手机号或者用户名是否唯一
        User user1 = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, registerParam.getUsername()));
        if (user1 != null){
            throw new RuntimeException("用户名已存在");
        }
        boolean exists = userMapper.exists(Wrappers.lambdaQuery(User.class)
                .eq(User::getPhone, registerParam.getPhone()));
        if (exists){
            throw new RuntimeException("手机号已存在");
        }

//        验证码的判断
        String code = redisUtil.getCacheObject(registerParam.getPhone());
        if (code == null){
            throw new RuntimeException("验证码已过期");
        }
        if (!code.equals(registerParam.getCode())){
            throw new RuntimeException("验证码错误");
        }
        if (!StringUtils.isEmpty(registerParam.getInviteCode())){
            UserNode inviteUser = neo4jUtils.getUserNode(Integer.valueOf(registerParam.getInviteCode()));
        }


        //判断邀请码是否有效
//        Long l = userMapper.selectCount(Wrappers.lambdaQuery(User.class)
//                .eq(User::getInviteCode, registerParam.getInviteCode()));
//           if (l <= 0){
//              throw new RuntimeException("邀请码无效");
//          }
        User parentUser = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getInviteCode, registerParam.getInviteCode()));
        if (parentUser == null){
            throw new RuntimeException("邀请码无效");
        }

        User user = new User();
//         user.setUsername(registerParam.getUsername());
//         user.setPassword(registerParam.getPassword());
//         user.setPhone(registerParam.getPhone());

        //设置父id
        user.setPid(parentUser.getId());

        /**
         * 属性拷贝，实现对象间同名属性的 拷贝
         */
        BeanUtils.copyProperties( registerParam,user);

        //利用hutool（加依赖） 生成邀请码，长度为6位
        String inviteCode = RandomUtil.randomString(6);

        //判断邀请码是否重复
        Long count = userMapper.selectCount(Wrappers.lambdaQuery(User.class)
                .eq(User::getInviteCode,inviteCode));
        if (count > 0){
            //本例是抛异常，实际也可以重新多次生成
            throw new RuntimeException("邀请码重复");
        }

        user.setInviteCode(inviteCode);
        userMapper.insert(user);

        //加入neo4j的执行结果，不影响注册结果，为了提高注册接口的执行效率
        //可以考虑异步执行图数据库的操作，利用线程池
        threadPoolExecutor.execute(() -> {
            //将用户信息添加到neo4j中
            UserNode pnode = neo4jUtils.getUserNode(parentUser.getId());
            if (pnode == null){
                pnode =  new UserNode();
                pnode.setId(parentUser.getId());
                pnode.setName(parentUser.getUsername());
                //neo4jUtils.addNode(pnode);
            }
            UserNode cnode = new UserNode();
            cnode.setId(user.getId());
            cnode.setName(user.getUsername());
            neo4jUtils.addNode(pnode,cnode);

        });





    }

    @Override
    public String login(LoginParam loginParam) {
        // 判断用户名和密码是否为空

        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getUsername, loginParam.getUsername()));
        if (user == null) {
            throw new RuntimeException("用户名错误");
        }
        if (!user.getPassword().equals(loginParam.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        Map<String, Object> map = new HashMap<>();
        map.put("uid", user.getId());
        // 生成jwt表示的token,不用将token存入redis
        String jwt = JwtUtils.createJwt(map);
        return jwt;
    }

    @Override
    public MyVO my() {
        //Integer uid = TokenUtils.getUidFromToken();
      Integer uid = UserUtils.getUid();
      User user = userMapper.selectById(uid);
      MyVO myVO = new MyVO();
      BeanUtils.copyProperties(user,myVO);
      myVO.setBalance(0);
      myVO.setPoint(0);
      myVO.setSignFlag(0);
        return myVO;
    }

    @Override
    public Map<String, Object> invite(Integer uid) {

        return neo4jUtils.findMapById(uid);
    }

    /**
     * 创建验证码，通过阿里云短信服务
     * @param phone
     */
    @Override
    public void createCode(String phone) {
        // 生成1000-9999之间的随机数（确保6位无前导零）
        int code = RandomUtil.randomInt(100000, 1000000); // 生成6位数字
        String key = String.format(RedisKeyEnum.KEY_CODE.getKey(), phone);
        redisUtil.setCacheObject(key, String.valueOf(code), RedisKeyEnum.KEY_CODE.getExpireTime(), TimeUnit.SECONDS);
        AliSmsUtils.sendSms(SmsEnum.SMS_CODE.getSignName(),
                SmsEnum.SMS_CODE.getTemplateCode(),
                phone,
                String.valueOf(code));
    }

    @Override
    public String uploadAvatar(MultipartFile file) {

        String filename = file.getOriginalFilename();
        String uuid = UUID.randomUUID().toString().replace("-", "");

        filename = uuid + filename.substring(filename.lastIndexOf("."));
        try {
          return  minioUtil.upload(filename, file.getInputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}
